/*
 * jxSwing Project (2012, 2013, 2014)
 * by Denilson Edinaldo Pinto
 * LGPL
 * Copyright (C) 2014
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package org.jxSwing.laf;

import java.awt.Component;
import java.util.ArrayList;
import java.util.List;

import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.UnsupportedLookAndFeelException;

import org.jxUtils.check.ParameterCheck;

/**
 * @author Denilson Edinaldo Pinto
 * @porject jxSwing
 * @package org.jxSwing.laf
 * @date 19/07/2014 - 11:51:18
 */
public class LookAndFeelUtil {
	
	public static final String GTK = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
	
	public static final String METAL = "javax.swing.plaf.metal.MetalLookAndFeel";
	
	public static final String MOTIF = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
	
	public static final String NIMBUS_JDK6 = "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel";
	
	public static final String NIMBUS_JDK7 = "javax.swing.plaf.nimbus.NimbusLookAndFeel";
	
	public static final String WINDOWS = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
	
	public static final String WINDOWS_CLASSIC = "com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel";
	
	/**
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws UnsupportedLookAndFeelException
	 */
	public static void applyGtk() throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
	
		applyLookAndFeel(GTK);
	}
	
	/**
	 * @param component
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws UnsupportedLookAndFeelException
	 */
	public static void applyGtk(final Component component) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
	
		applyGtk();
		
		//
		if(component != null) {
			
			SwingUtilities.updateComponentTreeUI(component);
		}
	}
	
	/**
	 * @param lookAndFeelClass
	 * @throws UnsupportedLookAndFeelException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 * @throws ClassNotFoundException
	 */
	public static void applyLookAndFeel(final Class<?> lookAndFeelClass) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
	
		applyLookAndFeel(lookAndFeelClass, null);
	}
	
	/**
	 * @param lookAndFeelClass
	 * @param component
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws UnsupportedLookAndFeelException
	 */
	public static void applyLookAndFeel(final Class<?> lookAndFeelClass, final Component component) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
	
		ParameterCheck.isNull(lookAndFeelClass, "lookAndFeelClass");
		
		applyLookAndFeel(lookAndFeelClass.getName(), component);
	}
	
	/**
	 * @param fullLookAndFeelClassName
	 * @throws UnsupportedLookAndFeelException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 * @throws ClassNotFoundException
	 */
	public static void applyLookAndFeel(final String fullLookAndFeelClassName) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
	
		applyLookAndFeel(fullLookAndFeelClassName, null);
	}
	
	/**
	 * @param fullLookAndFeelClassName
	 * @param component
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws UnsupportedLookAndFeelException
	 */
	public static void applyLookAndFeel(final String fullLookAndFeelClassName, final Component component) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
	
		ParameterCheck.isNullOrAbsoluteEmpty(fullLookAndFeelClassName, "fullLookAndFeelClassName");
		
		// Se o LookAndFeel está instalado
		if(getInstalledLookAndFeels().contains(fullLookAndFeelClassName.trim())) {
			
			UIManager.setLookAndFeel(fullLookAndFeelClassName);
			
			//
			if(component != null) {
				
				SwingUtilities.updateComponentTreeUI(component);
			}
			
		}else {
			
			throw new UnsupportedLookAndFeelException("O LookAndFeel " + fullLookAndFeelClassName.trim() + " não está instalado");
		}
	}
	
	/**
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws UnsupportedLookAndFeelException
	 */
	public static void applyMetal() throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
	
		applyLookAndFeel(METAL);
	}
	
	/**
	 * @param component
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws UnsupportedLookAndFeelException
	 */
	public static void applyMetal(final Component component) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
	
		applyMetal();
		
		//
		if(component != null) {
			
			SwingUtilities.updateComponentTreeUI(component);
		}
	}
	
	/**
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws UnsupportedLookAndFeelException
	 */
	public static void applyMotif() throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
	
		applyLookAndFeel(MOTIF);
	}
	
	/**
	 * @param component
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws UnsupportedLookAndFeelException
	 */
	public static void applyMotif(final Component component) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
	
		applyMotif();
		
		//
		if(component != null) {
			
			SwingUtilities.updateComponentTreeUI(component);
		}
	}
	
	/**
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws UnsupportedLookAndFeelException
	 */
	public static void applyNimbus() throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
	
		applyLookAndFeel(NIMBUS_JDK7);
	}
	
	/**
	 * @param component
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws UnsupportedLookAndFeelException
	 */
	public static void applyNimbus(final Component component) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
	
		applyNimbus();
		
		//
		if(component != null) {
			
			SwingUtilities.updateComponentTreeUI(component);
		}
	}
	
	/**
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws UnsupportedLookAndFeelException
	 */
	public static void applyWindows() throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
	
		applyLookAndFeel(WINDOWS);
	}
	
	/**
	 * @param component
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws UnsupportedLookAndFeelException
	 */
	public static void applyWindows(final Component component) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
	
		applyWindows();
		
		//
		if(component != null) {
			
			SwingUtilities.updateComponentTreeUI(component);
		}
	}
	
	/**
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws UnsupportedLookAndFeelException
	 */
	public static void applyWindowsClassic() throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
	
		applyLookAndFeel(WINDOWS_CLASSIC);
	}
	
	/**
	 * @param component
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws UnsupportedLookAndFeelException
	 */
	public static void applyWindowsClassic(final Component component) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
	
		applyWindowsClassic();
		
		//
		if(component != null) {
			
			SwingUtilities.updateComponentTreeUI(component);
		}
	}
	
	/**
	 * @return Look And Feels
	 */
	public static List<String> getInstalledLookAndFeels() {
	
		final List<String> lookAndFeels = new ArrayList<>();
		
		//
		for(final LookAndFeelInfo laf : getInstalledLookAndFeelsClass()) {
			
			lookAndFeels.add(laf.getClassName());
		}
		
		return lookAndFeels;
	}
	
	/**
	 * @return Look And Feels
	 */
	public static List<LookAndFeelInfo> getInstalledLookAndFeelsClass() {
	
		final List<LookAndFeelInfo> lookAndFeels = new ArrayList<>();
		
		//
		for(final UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
			
			lookAndFeels.add(laf);
		}
		
		return lookAndFeels;
	}
	
	/**
	 * @return Current Look And Feel
	 */
	public static LookAndFeel getLookAndFeel() {
	
		return UIManager.getLookAndFeel();
	}
}
